﻿using Common.Utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using Wallpaper.Services.IService;

namespace WallpaperApi.Controllers
{
    [Route("api/file")]
    [ApiController]
  
    public class FileController : ControllerBase
    {
        private readonly IMinioService _minioService;
        private readonly ILogger<FileController> _logger;

        public FileController(IMinioService minioService, ILogger<FileController> logger)
        {
            _minioService = minioService;
            _logger = logger;
        }

        /// <summary>
        /// 上传单个文件到 MinIO 存储服务
        /// </summary>
        /// <param name="file">用户上传的文件对象，包含文件数据和元信息</param>
        /// <param name="category">文件分类目录，用于按业务类型组织文件存储结构，默认为"general"</param>
        /// <returns>包含上传结果和文件信息的 JSON 响应</returns>
        /// <remarks>
        /// 文件存储路径规则：
        /// 1. 按分类目录组织：category/日期目录/文件名
        /// 2. 日期目录格式：yyyyMMdd（如：20250930）
        /// 3. 文件名格式：HH-mm-{GUID}.扩展名（如：17-14-16dae724-2383-4eb2-9055-ef720965b679.jpg）
        /// </remarks>
        [HttpPost("upload")]
        public async Task<ApiResponse<Object>> UploadFile(
            [Required] IFormFile file,
            [FromForm] string category = "general")
        {
            // 参数验证：检查文件是否为空
            if (file == null || file.Length == 0)
                
            return ApiResponse<Object>.Fail("文件不能为空");
            // 参数验证：检查文件大小限制（10MB）
            if (file.Length > 10 * 1024 * 1024)
            return ApiResponse<Object>.Fail("文件大小不能超过 10MB");

            try
            {
                // 生成文件存储路径和名称
                // 1. 获取文件扩展名并转换为小写，确保一致性
                var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();

                // 2. 生成日期目录（格式：yyyyMMdd）
                var dateFolder = DateTime.Now.ToString("yyyyMMdd");

                // 3. 生成时间前缀（格式：HH-mm，24小时制）
                var timePrefix = DateTime.Now.ToString("HH-mm");

                // 4. 生成全局唯一标识符
                var uniqueId = Guid.NewGuid().ToString();

                // 5. 构建完整的对象名称：分类/日期目录/时间-GUID.扩展名
                var objectName = $"{category.Trim('/')}/{dateFolder}/{timePrefix}-{uniqueId}{fileExtension}";

                // 使用文件流执行上传操作
                using var stream = file.OpenReadStream();
                var success = await _minioService.UploadFileAsync(objectName, stream, file.ContentType);

                if (success)
                {
                    // 获取文件的公开访问 URL
                    var fileUrl = _minioService.GetFileUrl(objectName);

                    // 返回上传成功的详细信息
                    return ApiResponse<object>.Success(new
                    {
                        message = "文件上传成功",
                        fileName = objectName,
                        url = fileUrl,
                        originalName = file.FileName,
                        size = file.Length,
                        contentType = file.ContentType,
                        category = category,
                        uploadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                    });
                }

                return ApiResponse<Object>.ServerError("文件上传失败");
            }
            catch (Exception ex)
            {
                _logger.LogDebug(ex, "文件上传处理异常 - 原始文件名: {FileName}, 分类: {Category}",
                    file.FileName, category);
               
                return ApiResponse<Object>.ServerError("文件上传处理失败");
            }
        }


        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="fileName">文件完整路径（格式：分类/日期目录/时间-GUID.扩展名）</param>
        /// <returns>文件流</returns>
        /// <remarks>
        /// 示例：/api/file/download?fileName=general/20250930/22-45-16dae724-2383-4eb2-9055-ef720965b679.jpg
        /// </remarks>
        [HttpGet("download")]
        public async Task<IActionResult> DownloadFile([FromQuery][Required] string fileName)
        {
            try
            {
                var fileStream = await _minioService.GetFileAsync(fileName);

                if (fileStream == null)
                    return NotFound(new { message = "文件不存在" });

                var contentType = GetContentType(fileName);
                var originalFileName = Path.GetFileName(fileName);

                return File(fileStream, contentType, originalFileName);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "文件下载失败 - 文件路径: {FileName}", fileName);
                return StatusCode(500, new { message = "文件下载失败" });
            }
        }

        /// <summary>
        /// 获取文件信息
        /// </summary>
        /// <param name="fileName">文件完整路径（格式：分类/日期目录/时间-GUID.扩展名）</param>
        /// <returns>文件信息</returns>
        /// <remarks>
        /// 示例：/api/file/info?fileName=general/20250930/22-45-16dae724-2383-4eb2-9055-ef720965b679.jpg
        /// </remarks>
        [HttpGet("info")]
        public async Task<ApiResponse<object>> GetFileInfo([FromQuery][Required] string fileName)
        {
            try
            {
                var exists = await _minioService.FileExistsAsync(fileName);
                if (!exists)
                    return ApiResponse<object>.Fail("文件不存在");

                var fileUrl = _minioService.GetFileUrl(fileName);
                return ApiResponse<object>.Success(new
                {
                    fileName,
                    url = fileUrl,
                    exists = true,
                    fileSize = await GetFileSizeAsync(fileName) // 可选：添加文件大小
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取文件信息失败 - 文件路径: {FileName}", fileName);
                return ApiResponse<object>.Fail("获取文件信息失败");
            }
        }

        /// <summary>
        /// 获取文件大小（如果需要）
        /// </summary>
        private async Task<long?> GetFileSizeAsync(string fileName)
        {
            try
            {
                // 如果 MinIO 服务支持获取文件信息，可以在这里实现
                // 或者通过其他方式获取文件大小
                return null;
            }
            catch
            {
                return null;
            }
        }


        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="fileName">文件完整路径（格式：分类/日期目录/时间-GUID.扩展名）</param>
        /// <returns>删除结果</returns>
        /// <remarks>
        /// 示例：/api/file/delete?fileName=general/20250930/22-45-16dae724-2383-4eb2-9055-ef720965b679.jpg
        /// </remarks>
        [HttpDelete("delete")]
        public async Task<ApiResponse<object>> DeleteFile([FromQuery][Required] string fileName)
        {
            try
            {
                var success = await _minioService.RemoveFileAsync(fileName);
                if (success)
                {
                    _logger.LogInformation("文件删除成功 - 文件路径: {FileName}", fileName);
                    return ApiResponse<object>.Success();
                }
                else
                {
                    return ApiResponse<object>.Fail("文件不存在");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "文件删除失败 - 文件路径: {FileName}", fileName);
                return ApiResponse<object>.Fail("文件删除失败");
            }
        }


        /// <summary>
        /// 批量上传文件
        /// </summary>
        [HttpPost("upload-multiple")]
        public async Task<IActionResult> UploadMultipleFiles(
            [Required] List<IFormFile> files,
            [FromForm] string category = "general")
        {
            if (files == null || !files.Any())
                return BadRequest(new { message = "没有上传文件" });

            var results = new List<object>();
            var successCount = 0;

            foreach (var file in files)
            {
                if (file.Length > 0 && file.Length <= 10 * 1024 * 1024)
                {
                    try
                    {
                        var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
                        var fileName = $"{Guid.NewGuid()}{fileExtension}";
                        var objectName = $"{category.Trim('/')}/{fileName}";

                        using var stream = file.OpenReadStream();
                        var success = await _minioService.UploadFileAsync(objectName, stream, file.ContentType);

                        if (success)
                        {
                            successCount++;
                            var fileUrl = _minioService.GetFileUrl(objectName);

                            results.Add(new
                            {
                                originalName = file.FileName,
                                fileName = objectName,
                                url = fileUrl,
                                size = file.Length,
                                contentType = file.ContentType,
                                success = true
                            });
                        }
                        else
                        {
                            results.Add(new
                            {
                                originalName = file.FileName,
                                success = false,
                                message = "上传失败"
                            });
                        }
                    }
                    catch (Exception ex)
                    {
                        results.Add(new
                        {
                            originalName = file.FileName,
                            success = false,
                            message = ex.Message
                        });
                    }
                }
                else
                {
                    results.Add(new
                    {
                        originalName = file.FileName,
                        success = false,
                        message = "文件大小不符合要求"
                    });
                }
            }

            return Ok(new
            {
                message = $"成功上传 {successCount}/{files.Count} 个文件",
                total = files.Count,
                success = successCount,
                failed = files.Count - successCount,
                results = results
            });
        }

        /// <summary>
        /// 根据文件扩展名获取 Content-Type
        /// </summary>
        private string GetContentType(string fileName)
        {
            var extension = Path.GetExtension(fileName).ToLowerInvariant();

            return extension switch
            {
                ".jpg" or ".jpeg" => "image/jpeg",
                ".png" => "image/png",
                ".gif" => "image/gif",
                ".bmp" => "image/bmp",
                ".webp" => "image/webp",
                ".pdf" => "application/pdf",
                ".txt" => "text/plain",
                ".zip" => "application/zip",
                ".rar" => "application/x-rar-compressed",
                ".doc" => "application/msword",
                ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                ".xls" => "application/vnd.ms-excel",
                ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                ".ppt" => "application/vnd.ms-powerpoint",
                ".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
                _ => "application/octet-stream"
            };
        }
    }
}